//
//  ViewController.m
//  CopyDemo
//
//  Created by 冯琰琰 on 2020/6/10.
//  Copyright © 2020 冯琰琰. All rights reserved.
//

#import "CopyViewController.h"
#import "Man.h"
#import "Person.h"

@interface CopyViewController ()
@property(strong,nonatomic)NSString *str;
@property(copy,nonatomic)NSString *str_copy;
@property(strong,nonatomic)NSMutableString *str_mutable;
@property(copy,nonatomic)NSMutableString *str_mutable_copy;
@end

@implementation CopyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.str = @"hahahahh";
    NSMutableString *mutableStr = [NSMutableString stringWithString:@"qwertyuiop"];
    NSLog(@"-----str----%p-------%@",self.str,self.str);
    self.str = mutableStr;
    [mutableStr appendString:@"333"];
    NSLog(@"-----str----%p-------%@",self.str,self.str);
    NSLog(@"-----mutableStr----%p-------%@",mutableStr,mutableStr);
    
//    -----str----0x600000354db0-------qwertyuiop333
//    -----mutableStr----0x600000354db0-------qwertyuiop333
//    strong关键字修饰 以上赋值操作为浅拷贝 ，地址相同  mutableStr变化 str 也会变化
    
    self.str_copy = @"hahahahh";
    NSLog(@"-----str_copy----%p-------%@",self.str_copy,self.str_copy);
    self.str_copy = mutableStr;
    [mutableStr appendString:@"5678"];
    NSLog(@"-----str_copy----%p-------%@",self.str_copy,self.str_copy);
    NSLog(@"-----mutableStr----%p-------%@",mutableStr,mutableStr);
//    -----str_copy----0x600002ee12c0-------qwertyuiop333
//    -----mutableStr----0x6000020b77e0-------qwertyuiop3335678
//   copy关键字修饰  以上赋值操作为深拷贝， 地址不同， mutableStr变化 ，str_copy 不会变化

    self.str_mutable = [NSMutableString stringWithString:@"hahhahaaaa"];
    NSLog(@"-----str_mutable----%p-------%@",self.str_mutable,self.str_mutable);
    self.str_mutable = mutableStr;
    [mutableStr appendString:@"qwert"];
    NSLog(@"-----str_mutable----%p-------%@",self.str_mutable,self.str_mutable);
    NSLog(@"-----mutableStr----%p-------%@",mutableStr,mutableStr);
//    -----str_mutable----0x600001e415f0-------qwertyuiop3335678qwert
//    -----mutableStr----0x600001e415f0-------qwertyuiop3335678qwert
//  strong关键字修饰 以上赋值操作为浅拷贝 ，地址相同  mutableStr变化 str_mutable 也会变化
    
    [self.str_mutable appendString:@"wo shi"]; // mutable 类型的变量 需要使用Strong去修饰
    NSLog(@"-----str_mutable---------%@",self.str_mutable.class);
    
    self.str_mutable_copy = [NSMutableString stringWithString:@"hahhahaaaa"];
    NSLog(@"-----str_mutable_copy----%p-------%@",self.str_mutable_copy,self.str_mutable_copy);
    self.str_mutable_copy = mutableStr;
    [mutableStr appendString:@"qwert"];
    NSLog(@"-----str_mutable_copy----%p-------%@",self.str_mutable_copy,self.str_mutable_copy);
    NSLog(@"-----mutableStr----%p-------%@",mutableStr,mutableStr);
    NSLog(@"-----str_mutable_copy---------%@",self.str_mutable_copy.class);
    //  copy关键字修饰 以上赋值操为浅拷贝 ，地址相同  mutableStr变化 str_mutable 也会变化
    
//    [self.str_mutable_copy appendString:@"beng"];  // Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:'   0x000000010feb8bc5   0x600002a249f0
    
    [self testCopyModelArray];
    
    [self testIvas];
    
    __block const char key = 0;
    objc_setAssociatedObject(self, &key, @1, OBJC_ASSOCIATION_ASSIGN);
}
-(void)testIvas{
    unsigned int  ivasCount;
    Ivar *ivas = class_copyIvarList([Person class], &ivasCount); // 获取当前类的所有实例变量信息,包括属性和成员变量，从 class_ro_t 中获取  仅输出当前的类的属性信息，而不会向上去找 superClass 中定义的属性。
    for (int i = 0; i < ivasCount ; i ++ ) {
        Ivar iva = ivas[i];
        NSString *key = [NSString stringWithUTF8String : ivar_getName(iva)];
        NSLog(@"class_copyIvarList-------key----%@",key);
    }
    unsigned int propertyCount;
    objc_property_t *propertys = class_copyPropertyList([Person class], &propertyCount);  // 获取类对象中的属性信息， class_rw_t 的 properties，先后输出了 category / extension/ baseClass 的属性，而且仅输出当前的类的属性信息，而不会向上去找 superClass 中定义的属性。
    for (int i = 0; i < propertyCount ; i ++) {
        objc_property_t property = propertys[i];
        NSString *key = [NSString stringWithUTF8String:property_getName(property)];
        NSLog(@"class_copyPropertyList-------key----%@",key);
    }
}
// 拷贝一个存放对象的数组，
-(void)testCopyModelArray{
    NSMutableArray *array_mutable = [NSMutableArray array];
    for (int i = 0 ; i < 5 ; i++) {
        Man *man1 = [Man new];
        man1.name = [@"Man.name" stringByAppendingString:@"hahaha"];
        [array_mutable addObject:man1];
    }
    NSArray *array_A = [NSArray arrayWithArray:array_mutable];
    
    NSArray *array_c = [[NSArray alloc] initWithArray:array_mutable copyItems:YES];
            
//    NSArray *array_B = [array_A mutableCopy];
    
//    NSMutableArray *array_B = [NSMutableArray array];
//    [array_A enumerateObjectsUsingBlock:^(Man *obj, NSUInteger idx, BOOL * _Nonnull stop) {
////        Man *man_B = [obj copy];
//        Man *man_B = [obj mutableCopy];
//        [array_B addObject:man_B];
//    }];

    
   // 归档 解档
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array_A];
    NSArray *array_B = [NSKeyedUnarchiver unarchiveObjectWithData:data];
//
//    NSError *error;
//    NSArray *array_B = [NSKeyedUnarchiver unarchivedObjectOfClass:Man.class fromData:[NSKeyedArchiver archivedDataWithRootObject:array_A requiringSecureCoding:YES error:&error] error:&error];
    
    NSLog(@"%@",array_B);
    
    Man *man1 = array_A.firstObject;
    man1.name = @"wo shi da longlong";
    NSLog(@"---------man1.name-----%@",man1.name);
    
    Man *man2 = array_B.firstObject;
    NSLog(@"---------man2.name-----%@",man2.name);
    
    Man *man3 = array_c.firstObject;
    NSLog(@"---------man3.name-----%@",man3.name);
    
    // 方案一:
    // 1.需要对象所属类遵守NSCoping协议
    // 2.需要实现copyWithZone这个方法 ，在这个方法里 通过[[self class] allocWithZone:zone];生成一个对象，并对对象赋值。
    // 3.遍历数组，调用对象的copy方法生成有个新的对象，添加到新的数组中去。
    
    // 方案二：
    // 1.需要对象所属类遵守NSCopying协议和NSMutableCoping协议
    // 2.需要实现需要实现copyWithZone这个方法 ，在这个方法里 通过[[self class] allocWithZone:zone];生成一个对象，并对对象赋值。
    // 3.新数组的生成调用方法 [[NSArray alloc] initWithArray:array_mutable copyItems:YES]; // copyItems设置为true的时候，会对数组的属性进行调用copyWithZone方法。对元素进行复制。// 但是对于元素中指针类型的成员变量，依然是浅拷贝，因此这种拷贝被称为单层深拷贝（one-level-deep copy）。
    
    // 方案三:
    // 1.对象所属类遵守协议NSCoding
    // 2.实现协议的方法
    // 3.归档再解档
   
}



@end
